#include <Riostream.h>
#include <CpLog.h>

#include "CpMagneticFieldMap.h"

ClassImp(CpMagneticFieldMap);

//______________________________________________________________________________
CpMagneticFieldMap::CpMagneticFieldMap(const char* name, const char* title, TString rootFile)
    : TNamed(name, title),
    fMagneticMapRootFileName(rootFile),
    fOutFile(0),
    fTree(0),
    fMagFieldObj(0)

{
//
// Constructor
//
  CpDebug(CpLog::kDebug + 5, "<-");
  CpDebug(CpLog::kDebug + 5, "->");
}

//______________________________________________________________________________
CpMagneticFieldMap::~CpMagneticFieldMap() {
//
// Destructor.
//

  CpDebug(CpLog::kDebug + 5, "<-");
  CpDebug(CpLog::kDebug + 5, "->");

}

//______________________________________________________________________________
void CpMagneticFieldMap::Reset() {
//
// Resets all variables
//
  CpDebug(CpLog::kDebug + 5, "<-");

  if (fOutFile) {
    fOutFile->Close();
    delete fOutFile;
    fOutFile = 0;
  }

  if (fTree) {
    delete fTree;
    fTree = 0;
  }

  if (fMagFieldObj) {
    delete fMagFieldObj;
    fMagFieldObj = 0;
  }
  CpDebug(CpLog::kDebug + 5, "->");
}


Bool_t CpMagneticFieldMap::OpenMagneticMapRootFile(TString fileName) {


  if (fileName.IsNull()) {
    if (fMagneticMapRootFileName.IsNull()) {
      CpError(Form("String fMagneticMapRootFile is %s !!! Exiting ...", fMagneticMapRootFileName.Data()));
      return kFALSE;
    }
  } else {
    fMagneticMapRootFileName = fileName.Data();
  }

  fOutFile = TFile::Open(fMagneticMapRootFileName.Data());
  if (!fOutFile) {
    CpError(Form("Error opening %s file !!!", fMagneticMapRootFileName.Data()));
    return kFALSE;
  }

  fTree = (TTree*) fOutFile->Get("ColdPigMagent");
  if (!fTree) {
    CpError("Error opening ColdPigMagent tree !!!");
    return kFALSE;
  }

  CpDebug(CpLog::kDebug, Form("File %s was open successfully ...", fMagneticMapRootFileName.Data()));

  return kTRUE;
}


//______________________________________________________________________________
Bool_t CpMagneticFieldMap::ImportFromTxtFile(TString infileName, TString outfileName) {
//
// Fills tree from the file
//
  CpDebug(CpLog::kDebug + 5, "<-");

  CpInfo(Form("Importing file %s ... ", infileName.Data()));

  Reset();

  fOutFile = TFile::Open(outfileName.Data(), "RECREATE");
  fTree = new TTree("ColdPigMagent", Form("%s", GetName()));
  fMagFieldObj = new CpMagneticFieldMapObject();
//     CpInfo(Form("%p",fMagFieldObj));
  fTree->Branch("field", &fMagFieldObj);

  const Int_t rows = 6;

  // Open the input stream
  ifstream fileIn;
  fileIn.open(infileName.Data());

  if (!fileIn.is_open()) {
    CpError(Form("File %s was not found. Skipping ...", infileName.Data()));
    return kFALSE;
  }

  Int_t count = 0;
  Int_t index;
  Double_t num[rows];

  Int_t i;
  for (i = 0;i < rows;i++)
    num[i] = 0.0;
  // Read the input list of files and add them to the chain
  TString line;
  while (fileIn.good()) {
    fileIn >> line;
    if (line.IsNull()) continue;
    index = count % rows;
    num[index] = line.Atof();
    if (index == rows - 1) {
      CpDebug(CpLog::kDebug + 4, Form("%.2E %.2E %.2E Bx=%.5E By=%.5E Bz=%.5E", num[0], num[1], num[2], num[3], num[4], num[5]));
      fMagFieldObj->SetPosition(num[0], num[1], num[2]);
      fMagFieldObj->SetMagField(num[3], num[4], num[5]);
      fTree->Fill();
      fMagFieldObj->Clear();
    }
    count++;
  }

//     fTree->Write();
  fTree->Write("", TObject::kOverwrite);
  CloseOutputFile();

  fMagneticMapRootFileName = outfileName.Data();
  CpInfo(Form("Importing file %s OK ... ", infileName.Data()));
  CpInfo(Form("File %s was created ... ", outfileName.Data()));
  CpDebug(CpLog::kDebug + 5, "->");
  return kTRUE;
}

Long64_t CpMagneticFieldMap::FillHistogram(TH1* hist, Int_t indexMag, Int_t indexAxis, Double_t axisOneAfter, Double_t axisTwoAfter) {

  CpDebug(CpLog::kDebug + 5, "<-");
  if (!OpenMagneticMapRootFile())
    return -1;

  Long64_t entriesAccepted = 0;
  CpMagneticFieldMapObject *obj = 0;
  fTree->SetBranchAddress("field", &obj);
//
  for (Int_t i = 0;i < fTree->GetEntries();i++) {
    CpDebug(CpLog::kDebug + 4, Form("Reading entry %d", i));
    fTree->GetEntry(i);
    if (!obj) continue;
//     CpDebug(CpLog::kDebug,Form("%d %f %f",indexAxis,obj->GetPos(kY),obj->GetPos(kZ)));
    if ((indexAxis == 0) && (obj->GetPos(1) == axisOneAfter) && (obj->GetPos(2) == axisTwoAfter)) {
      hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(0)), obj->GetMagField(indexMag));
      entriesAccepted++;
    } else if ((indexAxis == 1) && (obj->GetPos(0) == axisOneAfter) && (obj->GetPos(2) == axisTwoAfter)) {
      hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(1)), obj->GetMagField(indexMag));
      entriesAccepted++;
    } else if ((indexAxis == 2) && (obj->GetPos(0) == axisOneAfter) && (obj->GetPos(1) == axisTwoAfter)) {
      hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(2)), obj->GetMagField(indexMag));
      entriesAccepted++;
    }
  }

  CpDebug(CpLog::kDebug + 5, "->");
  return entriesAccepted;
}


Long64_t CpMagneticFieldMap::FillHistogram(TH2* hist, Int_t indexMag, Int_t indexAxis1, Int_t indexAxis2, Double_t axisAfter) {
  CpDebug(CpLog::kDebug + 5, "<-");
  if (!OpenMagneticMapRootFile())
    return -1;

  Long64_t entriesAccepted = 0;
  CpMagneticFieldMapObject *obj = 0;
  fTree->SetBranchAddress("field", &obj);

  for (Int_t i = 0;i < fTree->GetEntries();i++) {
    CpDebug(CpLog::kDebug + 4, Form("Reading entry %d", i));
    fTree->GetEntry(i);
    if (!obj) continue;
//         CpDebug(CpLog::kDebug,Form("%d %f %f",posAxis,obj->GetPos(kY),obj->GetPos(kZ)));
    if (((indexAxis1 == 0) && (indexAxis2 == 1)) || ((indexAxis1 == 1) && (indexAxis2 == 0))) {
      if (obj->GetPos(2) == axisAfter) {
        hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(0)), hist->GetYaxis()->FindBin(obj->GetPos(1)), obj->GetMagField(indexMag));
        entriesAccepted++;
      }
    } else if (((indexAxis1 == 1) && (indexAxis2 == 2)) || ((indexAxis1 == 2) && (indexAxis2 == 1))) {
      if (obj->GetPos(0) == axisAfter) {
        hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(1)), hist->GetYaxis()->FindBin(obj->GetPos(2)), obj->GetMagField(indexMag));
        entriesAccepted++;

      }
    } else if (((indexAxis1 == 2) && (indexAxis2 == 0)) || ((indexAxis1 == 0) && (indexAxis2 == 2))) {
      if (obj->GetPos(1) == axisAfter) {
        hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(0)), hist->GetYaxis()->FindBin(obj->GetPos(2)), obj->GetMagField(indexMag));
//         CpDebug(CpLog::kDebug,Form("%f %f %f",obj->GetPos(0),obj->GetPos(2),obj->GetMagField(indexMag)));
        entriesAccepted++;
      }
    }
  }

  CpDebug(CpLog::kDebug + 5, "->");
  return entriesAccepted;
}


Long64_t CpMagneticFieldMap::FillHistogram(TH3* hist, Int_t indexMag) {
  CpDebug(CpLog::kDebug + 5, "<-");
  if (!OpenMagneticMapRootFile())
    return -1;

  Long64_t entriesAccepted = 0;
  CpMagneticFieldMapObject *obj = 0;
  fTree->SetBranchAddress("field", &obj);
  Int_t i;
  for (i = 0;i < fTree->GetEntries();i++) {
    CpDebug(CpLog::kDebug + 4, Form("Reading entry %d", i));
    fTree->GetEntry(i);
    if (!obj) continue;
    hist->SetBinContent(hist->GetXaxis()->FindBin(obj->GetPos(0)), hist->GetYaxis()->FindBin(obj->GetPos(1)), hist->GetZaxis()->FindBin(obj->GetPos(2)), obj->GetMagField(indexMag));
    entriesAccepted++;
  }

  CpDebug(CpLog::kDebug + 5, "->");
  return entriesAccepted;
}

Bool_t CpMagneticFieldMap::VerifyDataWithFitFunction(TF3* fun, CpMagneticFieldMap::EAxis fieldAxis, Long64_t times) {

  CpDebug(CpLog::kDebug + 5, "<-");
  if (!OpenMagneticMapRootFile()) return -1;

  Double_t fitValue;
  CpMagneticFieldMapObject *obj = 0;
  fTree->SetBranchAddress("field", &obj);
  Int_t i;
  for (i = 0;i < fTree->GetEntries();i++) {
    CpDebug(CpLog::kDebug + 4, Form("Reading entry %d", i));
    fTree->GetEntry(i);
    if (!obj) continue;
    fitValue = fun->Eval(obj->GetPos(kX), obj->GetPos(kY), obj->GetPos(kZ));
    CpInfo(Form("[%.2f,%.2f,%.2f] %f %f", obj->GetPos(kX), obj->GetPos(kY), obj->GetPos(kZ), obj->GetMagField(fieldAxis)*times, fitValue));
  }

  CpDebug(CpLog::kDebug + 5, "->");
  return kTRUE;
}
